import os, glob
import threading
from time import sleep
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
import subprocess
import tempfile
# ffmpeg = os.path.join(os.path.dirname(__file__), "ffmpeg.exe")


class MyApp(tk.Frame):
    def __init__(self, parent):
        self.in_path = tk.StringVar()
        self.out_path = tk.StringVar()
        self.ffmpeg = os.path.join(os.path.dirname(__file__), "bin", "ffmpeg.exe")
        self.pprogress = 0
        self.progress = tk.IntVar(value=0)
        self.threads = tk.IntVar(value=0)
        tk.Frame.__init__(self)
        self.sem = threading.Semaphore(os.cpu_count())
        self.setup_widgets()
    
    def execv(self, cmd):
        ret = subprocess.run(cmd, 
                             stdout=subprocess.PIPE, 
                             stderr=subprocess.STDOUT, 
                             shell=False, 
                             creationflags=subprocess.CREATE_NO_WINDOW)
        return ret.stdout.decode('utf-8')

    def _compress(self, indir, outdir):
        self.progress.set(0)
        self.pprogress = 0
        if not os.path.isdir(outdir):
            os.makedirs(outdir)
        item = glob.glob(os.path.join(indir, "*.png"))
        if len(item) == 0:
            print("There is no png file found !")
            return
        self.progressbar.configure(maximum=len(item))
        for i in item:
            th = threading.Thread(target=self.__compress, args=[indir, outdir, i])
            th.daemon = True
            self.sem.acquire()
            th.start()
            self.threads.set(threading.active_count()-2)
        
        self.progress.set(self.pprogress)
        self.threads.set(threading.active_count()-2)
        sleep(3)
        self.pprogress = 0
        self.progress.set(self.pprogress)
        self.threads.set(threading.active_count()-2)

    # compress method from https://www.cnblogs.com/toumingbai/p/8298289.html
    def __compress(self, indir, outdir, i):
        tmppng = tempfile.mktemp() + ".png"
        cmd = [self.ffmpeg, "-i", i, "-vf", " palettegen=max_colors=256:stats_mode=single", "-y", tmppng]
        self.execv(cmd)
        out = os.path.join(outdir, os.path.basename(i))
        # if not os.path.isdir(outd): os.makedirs(outd)
        cmd = [self.ffmpeg, "-i", i, "-i", tmppng, "-lavfi", "[0][1:v] paletteuse", "-pix_fmt", "pal8", "-y", out]
        self.execv(cmd)
        self.pprogress += 1
        self.progress.set(self.pprogress)

        if os.path.isfile(tmppng): os.remove(tmppng)
        self.sem.release()
        return

    def compress(self, indir, outdir):
        th = threading.Thread(target=self._compress, args=[indir, outdir])
        th.daemon = True
        th.start()

    def choose_dir(self, p: tk.StringVar):
        p.set(os.path.abspath(filedialog.askdirectory()))

    def setup_widgets(self):
        l1 = ttk.Label(self, text="输入文件夹")
        e1 = ttk.Entry(self, textvariable=self.in_path, width=80)
        b1 = ttk.Button(self, text="选择文件夹", command=lambda:self.choose_dir(self.in_path))

        l2 = ttk.Label(self, text="输出文件夹")
        e2 = ttk.Entry(self, textvariable=self.out_path, width=80)
        b2 = ttk.Button(self, text="选择文件夹", command=lambda:self.choose_dir(self.out_path))

        cb = ttk.Button(self, text="开始压缩", command=lambda:self.compress(self.in_path.get(), self.out_path.get()))

        l1.grid(row=0, column=0, padx=5, pady=5)
        e1.grid(row=0, column=1, padx=5, pady=5)
        b1.grid(row=0, column=2, padx=5, pady=5)

        l2.grid(row=1, column=0, padx=5, pady=5)
        e2.grid(row=1, column=1, padx=5, pady=5)
        b2.grid(row=1, column=2, padx=5, pady=5)

        thl = ttk.Label(self, text="线程数:", anchor='e')
        thl2 = ttk.Label(self, textvariable=self.threads, anchor='e')
        thl.grid(row=2, column=0, padx=(5, 0), pady=5)
        thl2.grid(row=2, column=0, padx=(0, 5), pady=5, columnspan=2)

        cb.grid(row=2, column=2, columnspan=1, padx=5, pady=5)

        self.progressbar = ttk.Progressbar(self, length=700, orient='horizontal', variable=self.progress)
        self.progressbar.grid(row=3, column=0, padx=5, pady=5, columnspan=3)



if __name__ == '__main__':
    root = tk.Tk()
    root.title("PNG 批量压缩")

    ttk.Style(root).theme_use("vista")
    myapp = MyApp(root)
    myapp.pack(side='top')

    root.update()
    position = (( root.winfo_screenwidth() / 2 ) - ( root.winfo_width() / 2 ), \
                ( root.winfo_screenheight() / 2 ) - ( root.winfo_height() / 2 ))
    root.geometry("+%d+%d" %position)

    root.mainloop()